<template>
	<el-form-item
		v-if="itemState !== 'hidden'"
		:label="_label"
		:prop="_rulesProp"
		:rules="_rules"
		:class="['formItem', ..._itemClass]"
		:style="{
			..._formitemPrototypeStyle,
		}"
		v-bind="_formItemPrototype"
		v-on="_handlerEventFormItem">
		<Content
			v-model="formData"
			:config="itemConfig"
			:state="state"
			:fitContent="fitContent"
			:c_itemClass="_itemClass"
			v-bind="$attrs"
			:index="index"
			:showOverflowTooltip="false"
			:fromType="fromType">
			<template v-for="(slotName, index) in _slots" #[slotName]>
				<slot
					v-if="hasOwnPrototype($slots, slotName)"
					:name="slotName"></slot>
			</template>
			<template v-for="(slotName, index) in _slots" #[slotName]="scope">
				<slot
					v-if="hasOwnPrototype($scopedSlots, slotName)"
					:name="slotName"
					:row="scope.row"
					:index="scope.$index"></slot>
			</template>
		</Content>
	</el-form-item>
</template>
<script>
	import Content from '@/components/A/A-form/content/index.vue';
	export default {
		name: 'AFormitem',
		components: { Content },
		mixins: [],
		props: {
			value: {
				type: Object,
				default: () => ({}),
			},
			config: {
				type: Object,
				default: () => {},
			},
			state: {
				required: false,
				type: String,
			},

			label: { required: false, type: String },
			rulesProp: { required: false, type: String },
			fitContent: {
				type: Boolean,
				default: false,
			},
			fromType: {
				required: false,
				type: String,
			},
			index: { required: false, type: Number },
			layout: { required: false, type: Object },
		},
		data() {
			return {};
		},
		created() {
			if (this.itemConfig.type === 'checkboxGroup') {
				this.$set(this.formData, this.itemConfig.prop, []);
			}
		},

		filters: {},
		computed: {
			itemConfig: {
				get() {
					// return this.useVModel.call(this, this.FormItem, "FormItem");
					return this.config;
				},
				set(val) {
					this.$emit('config', val);
				},
			},

			formData: {
				get() {
					// return this.value;
					return this.useVModel.call(this);
				},
				set(val) {
					this.$emit('input', val);
				},
			},
			_rulesProp() {
				return (
					this.rulesProp ??
					this.itemConfig.rulesProp ??
					this.itemConfig.prop
				);
			},
			_show() {
				let show = true;
				if (Reflect.has(this.itemConfig, 'show')) {
					if (typeof this.itemConfig.show == 'function') {
						show = this.itemConfig.show({
							row: this.formData,
							index: this.index,
							val: this._.cloneDeep(
								this.formData[this.itemConfig.prop],
							),
						});
					} else if (typeof this.itemConfig.show == 'boolean') {
						show = this.itemConfig.show;
					}
				}
				return show;
			},
			itemState() {
				let state = '';
				if (this._show == false) {
					state = 'hidden';
				} else {
					if (typeof this.itemConfig.state == 'function') {
						state = this?.itemConfig?.state?.({
							row: this.formData,
							index: this.index,
							val: this._.cloneDeep(
								this.formData[this.itemConfig.prop],
							),
						});
					} else {
						state = this?.itemConfig?.state ?? this.state;
					}
				}
				return state;
			},
			_itemClass() {
				/**
				 * @fitBox 使内容撑满容器
				 * @blockBox 容器宽度为100%
				 * @flexBox 暂时不做处理
				 */
				if (this.c_itemClass?.length > 0) return this.c_itemClass;
				let classNames = [];
				let layout = Object.assign(
					this.itemConfig?.layout ?? {},
					this.layout ?? {},
				);
				layout.align ??= this.align;
				if (this.state) {
					if (this.state === 'write') {
						classNames.push('columnBox');
					}
					if (this.state === 'disabled') {
						classNames.push('columnBox');
					}
					if (this.state === 'readonly') {
						classNames.push('inlineBox');
					}
				} else {
					if (layout?.inline === true) {
						classNames.push('inlineBox');
					} else {
						if (this.itemState === 'readonly') {
							classNames.push('inlineBox');
						}
					}
					if (layout?.column === true) {
						classNames.push('columnBox');
					} else {
						if (this.itemState === 'write') {
							classNames.push('columnBox');
						}
						if (this.state === 'disabled') {
							classNames.push('columnBox');
						}
					}
				}

				if (layout?.fit === true) {
					classNames.push('fitBox');
				}
				if (layout?.block === true) {
					classNames.push('blockBox');
				}
				if (layout?.flex === true) {
					classNames.push('flexBox');
				}
				if (layout?.align === 'center') {
					classNames.push('centerBox');
				}
				if (layout?.align === 'left') {
					classNames.push('leftBox');
				}
				if (layout?.align === 'right') {
					classNames.push('rightBox');
				}
				if (layout?.align === 'right') {
					classNames.push('rightBox');
				}
				if (this.fromType === 'tableCloumns') {
					classNames.push('tableCloumnsBox');
				}
				if (this.fromType === 'formItems') {
					classNames.push('formItemsBox');
				}
				if (this._type === 'upload' || this._type === 'textarea') {
					if (layout?.block != false) {
						classNames.push('blockBox');
					}
					if (layout?.fit != false) {
						classNames.push('fitBox');
					}
				}

				let className_raw = layout?.className;
				let className = [];
				if (typeof className_raw === 'function') {
					className =
						className_raw({
							row: this.formData,
							val: this._.cloneDeep(
								this.formData[this.itemConfig.prop],
							),
							index: this.index,
						}) ?? [];
				} else if (Array.isArray(className)) {
					className = className_raw;
				} else {
					className = className_raw?.split(',');
				}
				let names = [];
				classNames?.map(item => {
					let name = item.toString().trim();
					if (!names.includes(name)) {
						names.push(name);
					}
					return name;
				});
				return names;
			},
			_type() {
				let type = 'text';
				if (
					Object.prototype.toString.call(this.itemConfig.type) ==
					'[object String]'
				) {
					type = this.itemConfig.type;
				}
				if (
					Object.prototype.toString.call(this.itemConfig.type) ==
					'[object Function]'
				) {
					type = this.itemConfig.type({
						row: this.formData,
						index: this.index,
						val: this._.cloneDeep(
							this.formData[this.itemConfig.prop],
						),
					});
				}
				return type;
			},
			_label() {
				let label = '';
				if (this.label) {
					label = this.label;
				} else {
					if (this._type === 'empty') {
						label = '';
					} else {
						if (
							Object.prototype.toString.call(
								this.itemConfig.type,
							) == '[object Function]'
						) {
							label = this.itemConfig.label({
								row: this.formData,
								index: this.index,
								val: this._.cloneDeep(
									this.formData[this.itemConfig.prop],
								),
							});
						} else {
							label = this.itemConfig?.label;
						}
					}
				}
				return label;
			},
			_rules() {
				let rule = [];
				if (!Reflect.has(this.itemConfig, 'type')) return rule;

				if (
					typeof this.itemConfig?.rules == 'boolean' &&
					this.itemConfig?.rules == true
				) {
					let trigger =
						this._type.includes('input') ||
						this._type === 'textarea'
							? 'blur'
							: 'change';
					let message_type =
						this._type.includes('input') ||
						this._type === 'textarea'
							? '输入'
							: '选择';
					let message_label = this.itemConfig?.label?.replace(
						/(选择|输入)/g,
						'',
					);
					let obj = {
						required: true,
						message: `请${message_type}${message_label}`,
						trigger,
					};
					rule.push(obj);
				} else if (
					Object.prototype.toString.call(this.itemConfig?.rules) ==
						'[object Array]' &&
					this.itemConfig?.rules?.length > 0
				) {
					rule = this?.itemConfig?.rules;
				} else if (
					Object.prototype.toString.call(this.itemConfig?.rules) ==
					'[object Function]'
				) {
					rule = this?.itemConfig?.rules?.({
						row: this.formData,
						index: this.index,
						val: this._.cloneDeep(
							this.formData[this.itemConfig.prop],
						),
					});
				}
				if (
					this.itemState === 'readonly' ||
					this.itemState === 'disabled' ||
					this._type === 'text' ||
					!this.hasOwnPrototype(this.itemConfig, 'type')
				) {
					return [];
				} else {
					return rule;
				}
			},
			_formItemPrototype() {
				return this.itemConfig?.prototype?.formItem ?? {};
			},
			_formitemPrototypeStyle() {
				return this.itemConfig?.layout?.style?.formItem ?? {};
			},
			_hideClear() {
				return !!this.itemConfig?.hideClear ?? true;
			},
			_handlerEventFormItem() {
				return this.itemConfig?.on?.formItem ?? {};
			},
			_slots() {
				if (this.Empty(this.itemConfig?.slot)) return [];
				let slots = [];
				if (typeof this.itemConfig.slot == 'function') {
					slots = this.itemConfig.slot({
						row: this.formData,
						index: this.index,
						val: this._.cloneDeep(
							this.formData[this.itemConfig.prop],
						),
					});
				}
				if (typeof this.itemConfig.slot == 'string') {
					slots = this.itemConfig.slot.split(',');
				}
				if (Array.isArray(this.itemConfig.slot)) {
					slots = this.itemConfig.slot;
				}
				return slots;
			},
		},
		watch: {
			_show: {
				handler(val, oldVal) {
					if (
						val === false &&
						oldVal === true &&
						'show' in this.itemConfig &&
						this._hideClear
					) {
						if (
							this.notEmpty(this.formData) &&
							this.notEmpty(this.itemConfig.prop)
						) {
							this.$set(
								this.formData,
								this.itemConfig.prop,
								void 0,
							);
						}
						if (
							this.notEmpty(this.formData) &&
							this.notEmpty(this.itemConfig.propLabel)
						) {
							this.$set(
								this.formData,
								this.itemConfig.propLabel,
								void 0,
							);
						}
						if (typeof this.itemConfig?.hideClear === 'string') {
							let keys = this.itemConfig?.hideClear?.split(',');
							keys?.map(key => {
								if (
									this.notEmpty(this.formData) &&
									this.notEmpty(this.itemConfig?.[key])
								) {
									this.$set(
										this.formData,
										this.itemConfig[key],
										void 0,
									);
								}
							});
						}
					}
				},
			},
		},
		mounted() {},
		methods: {
			hasOwnPrototype(obj, key) {
				if (typeof obj !== 'object') return false;
				return Reflect.has(obj, key);
			},
		},
	};
</script>
<style lang="scss" scoped>
	.tableCloumnsBox {
		margin-bottom: 0;
		// margin-top: 22px;
	}
</style>
